module ActiveRecord
  module Acts
    module OAuthProvider
      def self.included(base)
        base.extend ClassMethods
      end

      module ClassMethods
        def acts_as_oauth_provider
          return if self.included_modules.include?(ActiveRecord::Acts::OAuthProvider::ActMethods)
          
          @instance_klass = "#{self.name}Instance".constantize
          @instances_method = @instance_klass.name.tableize
          @instance_parent_method = self.name.tableize.singularize
          
          class_eval do
            include ActiveRecord::Acts::OAuthProvider::ActMethods
            validates_uniqueness_of :consumer_key

            def self.find_or_build_instance(controller)
              if !controller.params[:oauth_token].blank?
                instance = @instance_klass.find(:first, :conditions => 
                  ["request_token = ? AND access_token = request_token", controller.params["oauth_token"]]
                  ) || raise("Invalid token")
                provider = instance.send(@instance_parent_method)
              else
                provider = self.find_by_consumer_key(controller.params["oauth_consumer_key"]) || raise("Invalid token")
                instance = provider.send(@instances_method).build
              end

              valid = OAuth::Signature.verify(controller.request) do |token, consumer_key|
                [instance.request_secret, provider.consumer_secret]
              end
              logger.debug "verified as #{valid}"
              raise "Invalid signature" unless valid
              return instance
            end
          end
        end
      end
    
      module ActMethods
        def before_create
          begin
            self.consumer_key = rand(2**64)
            self.consumer_secret = rand(2**128)
          end while !self.valid?
        end
      end
    end
  end
end

ActiveRecord::Base.class_eval { include ActiveRecord::Acts::OAuthProvider }